/*
 * SequentialCore.cpp
 *
 *  Created on: Oct 18, 2012
 *      Author: David Kadlecek, Ales Fiser
 */

#include "SequentialCore.h"

SequentialCore::SequentialCore() {
	maxdepth = -1;
	maxresult = NULL;
	inputMatrix = NULL;
}

SequentialCore::~SequentialCore() {
	delete maxresult;
	delete inputMatrix;
}

void SequentialCore::loadInputMatrix(InputMatrixHolder* inputMatrix) {
	SequentialCore::inputMatrix = inputMatrix;
	maxresult = new int[SequentialCore::inputMatrix->getNumberOfNodes()];
}

void SequentialCore::checkAndSaveMaximum(Task* task) {
	if (logBasicDebugCore) cout << "try save max, check depth " << task->getDepth() << endl;
	if (maxdepth < task->getDepth()) {
		maxdepth = task->getDepth();
		if (logSavingMax) cout << "saving maximum with size: " << maxdepth + 1 << endl;

		for (int i = 0; i < inputMatrix->getNumberOfNodes(); ++i) {
			maxresult[i] = task->getActualState()[i];
		}
	}
}

short SequentialCore::isNotReasonToContinue() {
	if (maxdepth > (inputMatrix->getNumberOfNodes() / 2)) {
		return 1;
	}
	return 0;
}

int* SequentialCore::findClique(Task* task) {
	int lastIndex = 0;
	logPrintMessage("starting loop");
	while (task->haveWork()) {
		if (lastIndex != EMPTY && isPossibleClique(task->getActualState(), task->getDepth() + 1)) {
			lastIndex = task->nexByInreaseDepth(); // so far its clique, so increase depth
		} else {

			lastIndex = task->nextByWidth();	// its not clique, try next node at same level
			if (lastIndex == EMPTY) {
				task->decreaseDepth();			// there are not nodes at same level
				checkAndSaveMaximum(task);
				if (isNotReasonToContinue()) {
					//TODO
					break;
				}
				lastIndex = task->nextByWidth();  // at actual level node was already solved, try next at the same level
			}
		}
	}
	logPrintMessage("ending loop");
	return maxresult;
}

short SequentialCore::isPossibleClique(int* candidate, int sizeOfCandidate) {
	if (logBasicDebugCore) logPrintResult(candidate, inputMatrix->getNumberOfNodes());
	if (logBasicDebugCore) cout << "size of candidate to clique: " << sizeOfCandidate << endl;

	for (int i = 0; i < sizeOfCandidate; i++) {
		for (int j = 0; j < sizeOfCandidate; j++) {
			if (i == j) {
				continue;
			}
			if (isConnected(candidate[i], candidate[j]) == 0) {
				return 0;
			}
		}
	}
	return 1;
}

short SequentialCore::isConnected(int node1, int node2) {
	if (inputMatrix->getVlaue(node1, node2) == 1) {
		return 1;
	}
	if (logIsNotConnected) logPrintNodesNotConnected(node1, node2);
	return 0;
}

void SequentialCore::logPrintNodesNotConnected(int node1, int node2) {
	cout << "neni connect " << node1 << "  " << node2 << endl;
	int index = inputMatrix->getVlaue(node1, node2);
	cout << "nodes=" << inputMatrix->getNumberOfNodes() << "   index=" << index << "  node1=" << node1 << "  node2=" << node2 << "  v matici="
			<< inputMatrix->getVlaue(node1, node2) << endl;
}
